﻿// Fill out your copyright notice in the Description page of Project Settings.


#include "MultiThreading/SimpleRunnable.h"

FSimpleRunnable::FSimpleRunnable(const FString& ThreadName)
{
	// 获取 FEvent 指针
	ThreadEvent = FPlatformProcess::GetSynchEventFromPool();

	// 创建线程实例
	m_ThreadName = ThreadName;
	ThreadIns = FRunnableThread::Create(this, *m_ThreadName, 0, TPri_Normal);
	m_ThreadID = ThreadIns->GetThreadID();
	// UE_LOG(LogTemp, Warning, TEXT("Thread Start! ThreadID = %d"), m_ThreadID);
}

FSimpleRunnable::~FSimpleRunnable()
{
	if (ThreadEvent) // 清空 FEvent*
	{
		FPlatformProcess::ReturnSynchEventToPool(ThreadEvent); // delete ThreadEvent;
		ThreadEvent = nullptr;
	}
	if (ThreadIns) // 清空 FRunnableThread*
	{
		delete ThreadIns;
		ThreadIns = nullptr;
	}
}

bool FSimpleRunnable::Init()
{
	return true; //若返回 false ,线程创建失败，不会执行后续函数
}

uint32 FSimpleRunnable::Run()
{
	int32 count = 0;
	// FPlatformProcess::Sleep(0.03f); //延时，等待初始化完成
	while (bRun)
	{
		if (bPause)
		{
			ThreadEvent->Wait(); // 线程挂起
			if (!bRun) // 线程挂起时执行线程结束
			{
				return 0;
			}
		}
		// UE_LOG(LogTemp, Warning, TEXT("ThreadID: %d, Count: %d"), m_ThreadID, count);
		count++;
		FPlatformProcess::Sleep(0.1f); // 执行间隔，防止堵塞
	}
	return 0;
}

void FSimpleRunnable::Stop()
{
	bRun = false;
	bPause = false;
	if (ThreadEvent)
	{
		ThreadEvent->Trigger(); // 保证线程不挂起
	}
	Suspend(false); // 保证线程不挂起，本例只是为了暂时不同的挂起方法，如果不使用Suspend(),无需使用
}

void FSimpleRunnable::Exit()
{
	// UE_LOG(LogTemp, Warning, TEXT("Thread Exit!"));
}

void FSimpleRunnable::PauseThread()
{
	bPause = true;
	// UE_LOG(LogTemp, Warning, TEXT("Thread Pause!"));
}

void FSimpleRunnable::WakeUpThread()
{
	bPause = false;
	if (ThreadEvent)
	{
		ThreadEvent->Trigger(); // 唤醒线程
	}
	// UE_LOG(LogTemp, Warning, TEXT("Thread Wakeup!"));
}

void FSimpleRunnable::Suspend(bool bSuspend)
{
	if (ThreadIns)
	{
		ThreadIns->Suspend(bSuspend); //挂起/唤醒
	}
}

void FSimpleRunnable::StopThread()
{
	Stop();
	ThreadIns->WaitForCompletion(); // 等待线程执行完毕
}

void FSimpleRunnable::ShutDown(bool bShouldWait)
{
	if (ThreadIns)
	{
		ThreadIns->Kill(bShouldWait); // bShouldWait 为false，Suspend(true)时，会崩
	}
}


void AThreadingTestActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	if (SimpleRunnable) // 防止线程挂起，退出无响应
	{
		SimpleRunnable->StopThread();
		delete SimpleRunnable;
		SimpleRunnable = nullptr;
	}
}

void AThreadingTestActor::CreateNewThread(const FString& ThreadName)
{
	SimpleRunnable = new FSimpleRunnable(ThreadName);
}

void AThreadingTestActor::PauseThread()
{
	if (SimpleRunnable)
	{
		SimpleRunnable->PauseThread();
	}
}

void AThreadingTestActor::SuspendThread(bool bSuspend)
{
	if (SimpleRunnable)
	{
		SimpleRunnable->Suspend(bSuspend);
	}
}

void AThreadingTestActor::WakeUpThread()
{
	if (SimpleRunnable)
	{
		SimpleRunnable->WakeUpThread();
	}
}

void AThreadingTestActor::StopThread()
{
	if (SimpleRunnable)
	{
		SimpleRunnable->StopThread();
	}
}

void AThreadingTestActor::ForceKillThread(bool bShouldWait)
{
	if (SimpleRunnable)
	{
		SimpleRunnable->ShutDown(bShouldWait);
		delete SimpleRunnable;
		SimpleRunnable = nullptr;
	}
}
